/**
 * Yolema.com Inc.
 * Copyright (c) 2011-2012 All Rights Reserved.
 */
package org.grayrabbit.pay.facade.impl;

import java.text.SimpleDateFormat;

import org.apache.commons.lang.StringUtils;
import org.grayrabbit.pay.chinapay.ChinaPay;
import org.grayrabbit.pay.chinapay.common.PayConstant.CURRENCY_CODE;
import org.grayrabbit.pay.chinapay.common.PayConstant.PAY_TRADE_TYPE;
import org.grayrabbit.pay.chinapay.config.ChinaPayConfigUtil;
import org.grayrabbit.pay.core.biz.manager.trade.ChinaPayTradeManager;
import org.grayrabbit.pay.core.biz.vo.ChinaPayTradeVo;
import org.grayrabbit.pay.core.model.entity.system.AppSystem;
import org.grayrabbit.pay.core.model.entity.transaction.Trade;
import org.grayrabbit.pay.core.model.exception.PayException;
import org.grayrabbit.pay.core.model.results.GenericsResult;
import org.grayrabbit.pay.core.model.utils.AppSystemUtil;
import org.grayrabbit.pay.facade.ChinapayClient;
import org.grayrabbit.pay.facade.bean.ChinaPayForm;
import org.grayrabbit.pay.facade.bean.ChinaPayTrade;
import org.grayrabbit.pay.facade.bean.Money;
import org.grayrabbit.pay.facade.bean.TradeMapping;
import org.grayrabbit.pay.facade.bean.TradeReturn;
import org.grayrabbit.pay.facade.common.Result;
import org.grayrabbit.pay.facade.common.TradeConstants.RefundCode;
import org.grayrabbit.pay.facade.common.TradeConstants.TradeCode;
import org.grayrabbit.pay.facade.common.TradeParam;
import org.grayrabbit.pay.facade.convert.ChinaPayTradeConvert;
import org.grayrabbit.pay.facade.exception.ParamException;
import org.grayrabbit.pay.facade.exception.PayClientException;
import org.grayrabbit.pay.facade.exception.PermissionException;
import org.grayrabbit.pay.trade.TradeChinaPayInfo;
import org.grayrabbit.pay.trade.TradeMoney;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * payclient接口实现类
 * 
 * @author wangy
 * @version $Id: PayImpl.java, v 0.1 2012-6-4 下午5:40:22 wy Exp $
 */
@Component
public class ChinapayClientImpl implements ChinapayClient {

	private static final Logger LOG = LoggerFactory
			.getLogger(ChinapayClientImpl.class);

	@Value("${pay.url}")
	private String payUrl;

	@Autowired
	private ChinaPayTradeManager chinaPayTradeManager;

	@Override
	public Result<ChinaPayForm> getChinaPayForm(ChinaPayTrade chinaPayTrade) {
		Result<ChinaPayForm> result = new Result<ChinaPayForm>();
		try {

			validate(chinaPayTrade);

			ChinaPayTradeVo chinaPayTradeVo = new ChinaPayTradeVo();

			ChinaPayTradeConvert.convert(chinaPayTrade, chinaPayTradeVo);

			GenericsResult<Trade> genericsResult = chinaPayTradeManager
					.saveTrade(chinaPayTradeVo);

			if (!genericsResult.isSuccess()) {
				result.setIsSuccess(false);
				result.setResultCode(genericsResult.getResultCode());
				result.setResultMsg(genericsResult.getResultMsg());
				return result;
			}
			Trade t = genericsResult.getResultData();

			String transId = t.getOrderTradeId();
			// 转换订单信息，调用银联相关接口
			TradeChinaPayInfo tradeChinaPayInfo = new TradeChinaPayInfo();
			tradeChinaPayInfo.setTradeId(transId);
			tradeChinaPayInfo.setCurrencyCode(CURRENCY_CODE.RMB);
			tradeChinaPayInfo.setMoney(new TradeMoney().convertFen(t
					.getTradeMoney()));
			tradeChinaPayInfo.setPayTradeType(PAY_TRADE_TYPE.TRANS_TYPE_PAY);
			tradeChinaPayInfo.setTransDate(new SimpleDateFormat("yyyyMMdd")
					.format(t.getTradeDate()));
			ChinaPay.signOrder(tradeChinaPayInfo);
			ChinaPayForm chinaPayForm = new ChinaPayForm();
			chinaPayForm.setFormUrl(ChinaPayConfigUtil.getChinaPayInfo()
					.getTradeUrl());
			chinaPayForm.setOrderId(chinaPayTrade.getOrderId());
			chinaPayForm.setTransId(transId);
			chinaPayForm.setParams(TradeParam.getParams(tradeChinaPayInfo, t,
					true, payUrl));
			result.setData(chinaPayForm);
			result.setTradeId(transId);
		} catch (PayException pe) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pe.getResultCode());
			result.setResultMsg(pe.getResultMsg());
			LOG.error("PayException异常,{}:{}", pe.getResultCode(),
					pe.getResultMsg());
		} catch (PayClientException pce) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pce.getErrorCode());
			result.setResultMsg(pce.getErrorMsg());
			LOG.error("PayClientException异常,{}:{}", pce.getErrorCode(),
					pce.getErrorMsg());
		} catch (Exception e) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(Result.DEFAULT_EXCEPTION);
			result.setResultMsg(e.getMessage());
			LOG.error("未知异常", e);
		}
		return result;
	}

	@Override
	public Result<ChinaPayForm> getChinaPayRefundForm(
			ChinaPayTrade chinaPayTrade) {
		Result<ChinaPayForm> result = new Result<ChinaPayForm>();
		try {
			validate(chinaPayTrade);

			ChinaPayTradeVo chinaPayTradeVo = new ChinaPayTradeVo();

			ChinaPayTradeConvert.convert(chinaPayTrade, chinaPayTradeVo);

			GenericsResult<Trade> genericsResult = chinaPayTradeManager
					.saveRefundTrade(chinaPayTradeVo);

			if (!genericsResult.isSuccess()) {
				result.setIsSuccess(false);
				result.setResultCode(genericsResult.getResultCode());
				result.setResultMsg(genericsResult.getResultMsg());
				return result;
			}
			Trade trade = genericsResult.getResultData();

			TradeChinaPayInfo tradeChinaPayInfo = new TradeChinaPayInfo();
			tradeChinaPayInfo.setTradeId(trade.getOrderTradeId());
			tradeChinaPayInfo.setCurrencyCode(CURRENCY_CODE.RMB);
			tradeChinaPayInfo.setMoney(new TradeMoney().convertFen(trade
					.getTradeMoney()));
			tradeChinaPayInfo.setPayTradeType(PAY_TRADE_TYPE.TRANS_TYPE_REFUND);
			tradeChinaPayInfo.setTransDate(new SimpleDateFormat("yyyyMMdd")
					.format(trade.getTradeDate()));
			ChinaPayForm chinaPayForm = new ChinaPayForm();
			chinaPayForm.setFormUrl(ChinaPayConfigUtil.getChinaPayInfo()
					.getRefundUrl());
			chinaPayForm.setOrderId(chinaPayTrade.getOrderId());
			chinaPayForm.setTransId(trade.getOrderTradeId());
			chinaPayForm.setParams(TradeParam.getParams(tradeChinaPayInfo,
					trade, false, payUrl));
			result.setData(chinaPayForm);
			result.setTradeId(trade.getOrderTradeId());

		} catch (PayException pe) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pe.getResultCode());
			result.setResultMsg(pe.getResultMsg());
			LOG.error("PayException异常,{}:{}", pe.getResultCode(),
					pe.getResultMsg());
		} catch (PayClientException pce) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pce.getErrorCode());
			result.setResultMsg(pce.getErrorMsg());
			LOG.error("PayClientException异常,{}:{}", pce.getErrorCode(),
					pce.getErrorMsg());
		} catch (Exception e) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(Result.DEFAULT_EXCEPTION);
			result.setResultMsg(e.getMessage());
			LOG.error("未知异常", e);
		}
		return result;
	}

	@Override
	public Result<RefundCode> refundResult(ChinaPayTrade chinaPayTrade) {
		Result<RefundCode> result = new Result<RefundCode>();
		try {
			validate(chinaPayTrade);

			ChinaPayTradeVo chinaPayTradeVo = new ChinaPayTradeVo();

			ChinaPayTradeConvert.convert(chinaPayTrade, chinaPayTradeVo);

			GenericsResult<String> genericsResult = chinaPayTradeManager
					.refundStatus(chinaPayTradeVo);

			if (!genericsResult.isSuccess()) {
				result.setIsSuccess(false);
				result.setResultCode(genericsResult.getResultCode());
				result.setResultMsg(genericsResult.getResultMsg());
				return result;

			}

			result.setData(RefundCode.getRefundEnum(genericsResult
					.getResultData()));
			return result;

		} catch (PayException pe) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pe.getResultCode());
			result.setResultMsg(pe.getResultMsg());
			LOG.error("PayException异常,{}:{}", pe.getResultCode(),
					pe.getResultMsg());
		} catch (PayClientException pce) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pce.getErrorCode());
			result.setResultMsg(pce.getErrorMsg());
			LOG.error("PayClientException异常,{}:{}", pce.getErrorCode(),
					pce.getErrorMsg());
		} catch (Exception e) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(Result.DEFAULT_EXCEPTION);
			result.setResultMsg(e.getMessage());
			LOG.error("未知异常", e);
		}
		return result;
	}

	@Override
	public Result<TradeCode> payResult(ChinaPayTrade chinaPayTrade) {
		Result<TradeCode> result = new Result<TradeCode>();
		try {
			validate(chinaPayTrade);

			ChinaPayTradeVo chinaPayTradeVo = new ChinaPayTradeVo();

			ChinaPayTradeConvert.convert(chinaPayTrade, chinaPayTradeVo);

			GenericsResult<Trade> genericsResult = chinaPayTradeManager
					.tradeStatus(chinaPayTradeVo);

			if (!genericsResult.isSuccess()) {
				result.setIsSuccess(false);
				result.setResultCode(genericsResult.getResultCode());
				result.setResultMsg(genericsResult.getResultMsg());
				return result;
			}

			result.setData(TradeCode.getTradeEnum(genericsResult
					.getResultData().getTradeStatus()));
			result.setTradeId(genericsResult.getResultData().getOrderTradeId());
			return result;

		} catch (PayException pe) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pe.getResultCode());
			result.setResultMsg(pe.getResultMsg());
			LOG.error("PayException异常,{}:{}", pe.getResultCode(),
					pe.getResultMsg());
		} catch (PayClientException pce) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pce.getErrorCode());
			result.setResultMsg(pce.getErrorMsg());
			LOG.error("PayClientException异常,{}:{}", pce.getErrorCode(),
					pce.getErrorMsg());
		} catch (Exception e) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(Result.DEFAULT_EXCEPTION);
			result.setResultMsg(e.getMessage());
			LOG.error("未知异常", e);
		}
		return result;
	}

	/**
	 * 验证应用是否有权限
	 * 
	 * @param systemCode
	 */
	private void validate(ChinaPayTrade chinaPayTrade) {
		if (chinaPayTrade == null) {
			throw new ParamException("chinaPayTrade is Null");
		}
		if (StringUtils.isBlank(chinaPayTrade.getSystemCode())) {
			throw new PermissionException();
		}
		if (StringUtils.isBlank(chinaPayTrade.getOrderId())) {
			throw new ParamException("OrderId is Null");
		}
		if (chinaPayTrade.getOrderId().length() > 32) {
			throw new ParamException("OrderId length max 32");
		}
		AppSystem appSystem = AppSystemUtil.getAppSystem(chinaPayTrade
				.getSystemCode());
		if (appSystem == null) {
			throw new PermissionException();
		}
		// TODO 以后可能需要对系统可使用的交易终端进行验证，暂只有银联，不做验证
	}

	/**
	 * @see org.grayrabbit.pay.facade.ChinapayClient#payMappingByTrans()
	 */
	@Override
	public Result<TradeMapping> payMappingByTrans(TradeReturn tradeReturn) {

		Result<TradeMapping> result = new Result<TradeMapping>();
		try {
			if (tradeReturn == null) {
				throw new ParamException("tradeReturn is Null");
			}
			if (StringUtils.isBlank(tradeReturn.getSystemCode())) {
				throw new PermissionException();
			}
			AppSystem appSystem = AppSystemUtil.getAppSystem(tradeReturn
					.getSystemCode());
			if (appSystem == null) {
				throw new PermissionException();
			}
			if ((StringUtils.isBlank(tradeReturn.getTransId()) || tradeReturn
					.getTransId().length() != 16)
					&& StringUtils.isBlank(tradeReturn.getOrderId())) {
				throw new ParamException(
						"trandsId is Null or trandsId length is not 16 or orderId is Null");
			}

			GenericsResult<Trade> genericsResult = chinaPayTradeManager.query(
					tradeReturn.getSystemCode(), tradeReturn.getTransId(),
					tradeReturn.getOrderId());

			if (!genericsResult.isSuccess()) {
				result.setIsSuccess(false);
				result.setResultCode(genericsResult.getResultCode());
				result.setResultMsg(genericsResult.getResultMsg());
				return result;
			}
			Trade t = genericsResult.getResultData();

			TradeMapping tradeMapping = new TradeMapping();
			tradeMapping.setMemo(t.getMemo());
			tradeMapping.setMoney(new Money().convertFen(t.getTradeMoney()));
			tradeMapping.setName(t.getTradeName());
			tradeMapping.setOrderId(t.getOrderId());
			tradeMapping.setTransId(t.getOrderTradeId());
			tradeMapping.setUser(t.getOperater());
			tradeMapping
					.setTradeCode(TradeCode.getTradeEnum(t.getTradeStatus()));
			result.setData(tradeMapping);
			result.setTradeId(t.getOrderTradeId());
			return result;

		} catch (PayException pe) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pe.getResultCode());
			result.setResultMsg(pe.getResultMsg());
			LOG.error("PayException异常,{}:{}", pe.getResultCode(),
					pe.getResultMsg());
		} catch (PayClientException pce) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(pce.getErrorCode());
			result.setResultMsg(pce.getErrorMsg());
			LOG.error("PayClientException异常,{}:{}", pce.getErrorCode(),
					pce.getErrorMsg());
		} catch (Exception e) {
			result.setIsSuccess(Boolean.FALSE);
			result.setResultCode(Result.DEFAULT_EXCEPTION);
			result.setResultMsg(e.getMessage());
			LOG.error("未知异常", e);
		}

		return result;
	}

}
